package com.joysuch.wwyt.patrol.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
import com.joysuch.wwyt.common.constant.Constant;
import com.joysuch.wwyt.patrol.constant.CheckResultStatus;
import com.joysuch.wwyt.patrol.constant.TaskStatus;
import com.joysuch.wwyt.patrol.entity.PatrolCheckPlan;
import com.joysuch.wwyt.patrol.entity.PatrolCheckPoint;
import com.joysuch.wwyt.patrol.entity.PatrolTask;
import com.joysuch.wwyt.patrol.entity.PatrolUnfinishTask;
import com.joysuch.wwyt.patrol.entity.bean.UncheckSnapshotParam;
import com.joysuch.wwyt.patrol.mapper.PatrolUnfinishTaskMapper;
import com.joysuch.wwyt.patrol.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author heqifeng
 * @since 2022-03-01
 */
@Service
public class PatrolUnfinishTaskServiceImpl extends ServiceImpl<PatrolUnfinishTaskMapper, PatrolUnfinishTask> implements PatrolUnfinishTaskService {

    @Autowired
    private PatrolUnfinishTaskMapper mapper;
    @Autowired
    private PatrolRecordService recordService;
    @Autowired
    private PatrolTaskService taskService;
    @Autowired
    private PatrolCheckPlanService patrolCheckPlanService;
    @Autowired
    private PatrolSnapshotPathService snapshotPathService;


    @Override
    public PatrolUnfinishTask genUnFinishMappingByTask(PatrolTask task) {
        Long taskId = task.getId();
        PatrolUnfinishTask unfinishTask = new PatrolUnfinishTask();
        unfinishTask.setTaskId(taskId).setDeadLine(task.getDeadLine());
        return unfinishTask;
    }

    @Override
    public boolean deleteUnFinishTaskMapping(Long taskId) {
        Integer deleted = mapper.deleteByTaskId(taskId);
        if (deleted != null && deleted > 0) {
            return true;
        }
        return false;
    }

    @Scheduled(cron = "0 0/15 * * * ?")
    public void scan() {
        scanUncheckTask();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void scanUncheckTask() {
        // 已到截止时间且未完成的任务id
        Date currDate = new Date();
        List<Long> uncheckTaskIds = mapper.getExpiredTsakIds(currDate);
        List<UncheckSnapshotParam> snapshotParams = new ArrayList<>();
        //分批处理
        if (CollectionUtil.isNotEmpty(uncheckTaskIds)){
            List<List<Long>> uncheckTaskIdList = Lists.partition(uncheckTaskIds,50000);
            for (List<Long> list : uncheckTaskIdList){
                Collection<PatrolTask> tasks = taskService.listByIds(list);
                List<Long> plantIds = tasks.stream().map(PatrolTask::getPlanId).collect(Collectors.toList());
                Collection<PatrolCheckPlan> patrolCheckPlans = patrolCheckPlanService.listByIds(plantIds);
                Map<Long, String> map = new HashMap<>();
                if (CollectionUtil.isNotEmpty(patrolCheckPlans)) {
                    map = patrolCheckPlans.stream().collect(Collectors.toMap(PatrolCheckPlan::getId, PatrolCheckPlan::getDeviceStopAutoProcess));
                }
                if (CollectionUtil.isNotEmpty(tasks)) {
                    // 检查点是否正常 集合
                    Map<Long, Boolean> taskCheckResultMap = new HashMap<>();
                    for (PatrolTask task : tasks) {
                        List<PatrolCheckPoint> points = recordService.getUncheckPointByTaskId(task.getId());
                        // 检查点检查结果
                        List<String> pointCheckResultList = Lists.newArrayList();
                        for (PatrolCheckPoint point : points) {
                            // 生成任务的附属数据，record、recordItem
                            String checkResult = recordService.genRecordByPoint(point, task, map.get(task.getPlanId()));
                            pointCheckResultList.add(checkResult);
                        }
                        // 任务检查点检查结果均正常, 则任务检查结果也为正常
                        long unNormalNum = pointCheckResultList.stream().filter(checkResult -> !CheckResultStatus.NORMAL.equals(checkResult)).count();
                        if (CollectionUtil.isNotEmpty(points) && unNormalNum == 0) {
                            taskCheckResultMap.put(task.getId(), true);
                        }
                    }
                    // 处理任务的各种状态
                    tasks.forEach(task -> {
                        Boolean normal = taskCheckResultMap.get(task.getId());
                        String taskCheckResult = normal != null && normal ? CheckResultStatus.NORMAL : CheckResultStatus.ABNORMAL;
                        task.setStatus(TaskStatus.FINISHED)
                                .setCheckEndTime(currDate)
                                .setCheckResult(CheckResultStatus.ABNORMAL)
                                .setTimeCost(Objects.isNull(task.getTimeCost()) ? 0L : task.getTimeCost())
                                .setFinishDate(new Date());
                        // fix：27898
                        if (Objects.nonNull(task.getTimeCost()) && Objects.nonNull(task.getCheckUser())) {
                            // 存在检查人和花费时间，表示此任务下存在已检的检查点，需要补充路线快照（时间范围：）
                            snapshotParams.add(new UncheckSnapshotParam(task.getId(), task.getCheckUser(),
                                    task.getCheckStartTime(), task.getCheckEndTime(), task.getTenentId(), task.getOrgCode(), null));
                        }else {
                            task.setCheckStartTime(currDate);
                            task.setTimeCost(0L);
                        }
                        // fix：27898
                        if (Objects.nonNull(task.getTimeCost()) && Objects.nonNull(task.getCheckUser())) {
                            // 存在检查人和花费时间，表示此任务下存在已检的检查点，需要补充路线快照（时间范围：第一次提交检查点时间-任务截止时间）
                            snapshotParams.add(new UncheckSnapshotParam(task.getId(), task.getCheckUser(),
                                    task.getCheckStartTime(), task.getCheckEndTime(), task.getTenentId(), task.getOrgCode(), null));
                        }else {
                            task.setCheckStartTime(currDate);
                            task.setTimeCost(0L);
                        }
                        //逾期状态 0未逾期 1逾期
                        task.setSlippageStatus(1);
                        String exceptReason = task.getExceptReason();
                        List<String> reasonList = new ArrayList<>();
                        if (StringUtils.isNotBlank(exceptReason)) {
                            reasonList.addAll(Splitter.on(Constant.SPLIT_COMMA).trimResults().splitToList(exceptReason));
                        }
                        // 当前异常原因无“漏检”，则新增“漏检”并更新，已有则不新增
                        boolean addReason = !reasonList.contains("漏检") && reasonList.add("漏检");
                        if (addReason && !CheckResultStatus.NORMAL.equals(taskCheckResult)) {
                            task.setExceptReason(reasonList.stream().collect(Collectors.joining(Constant.SPLIT_COMMA)));
                        }
                    });
                    if (CollectionUtil.isNotEmpty(tasks)) {
                        taskService.saveOrUpdateBatch(tasks);
                    }
                    mapper.deleteByTaskIds(list);
                }
            }
        }
        // 补充快照
        if (CollectionUtil.isNotEmpty(snapshotParams)) {
            snapshotPathService.saveSnapshotPath4Uncheck(snapshotParams);
        }
        // 补充快照
        if (CollectionUtil.isNotEmpty(snapshotParams)) {
            snapshotPathService.saveSnapshotPath4Uncheck(snapshotParams);
        }
    }

    @Override
    public Integer batchSave(List<PatrolUnfinishTask> entityList, Integer batchSize) {
        Integer insertCount = 0;
        List<List<PatrolUnfinishTask>> entityPages = Lists.partition(entityList, batchSize);
        for(List<PatrolUnfinishTask> entityPage : entityPages) {
            mapper.batchInsert(entityPage);
            insertCount += entityPage.size();
        }
        return insertCount;
    }

}
